package com.tiancheng.trade.settlement.service.settlement.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tiancheng.trade.commom.core.data.PageInfo;
import com.tiancheng.trade.commom.core.utils.DateTimeUtil;
import com.tiancheng.trade.settlement.bo.ExportBO;
import com.tiancheng.trade.settlement.bo.SSettleLettersDetailExportBo;
import com.tiancheng.trade.settlement.bo.SSettleLettersDetailQueryBO;
import com.tiancheng.trade.settlement.configuration.CmbConfiguration;
import com.tiancheng.trade.settlement.enums.LettersTypeEnum;
import com.tiancheng.trade.settlement.enums.OrderSourceEnum;
import com.tiancheng.trade.settlement.enums.RevenueTypeEnum;
import com.tiancheng.trade.settlement.mapper.settlement.SSettleLettersDetailMapper;
import com.tiancheng.trade.settlement.model.settlement.SSettleLettersDetail;
import com.tiancheng.trade.settlement.service.settlement.ISSettleLettersDetailService;
import com.tiancheng.trade.settlement.service.settlement.ISSettleLettersService;
import com.tiancheng.trade.settlement.util.*;
import com.tiancheng.trade.settlement.vo.settlement.admin.SSettleLettersDetailQueryVo;
import com.tiancheng.trade.settlement.vo.settlement.admin.SettleLetterAdjustVo;
import com.tiancheng.trade.settlement.vo.settlement.admin.res.SSettleLettersDetailResVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static com.tiancheng.trade.settlement.exception.error.BusinessErrorInfoEnum.REVENUE_DATE_TOO_LONG;
import static com.tiancheng.trade.settlement.exception.error.BusinessErrorInfoEnum.REVENUE_SETTLE_LETTERS_NOT_FOUND_ERROR;

/**
 * @Auther: Likailun
 * @Date: 11:13 2021/5/8
 * @Description: 对账函service impl
 */
@Slf4j
@Service
public class SSettleLettersDetailServiceImpl extends ServiceImpl<SSettleLettersDetailMapper, SSettleLettersDetail> implements ISSettleLettersDetailService {


    @Autowired
    CmbConfiguration cmbConfiguration;
    @Resource
    private IdGenerateUtil idGenerateUtil;
    @Autowired
    private ISSettleLettersService settleLettersService;


    @Override
    public PageInfo<SSettleLettersDetailResVO> queryLit(SSettleLettersDetailQueryBO queryVo) {
        if (queryVo.getSettleEnd().until(queryVo.getSettleStart(), ChronoUnit.DAYS) > 31) {
            REVENUE_DATE_TOO_LONG.assertFail();
        }
        queryVo.buildStart();
        LambdaQueryWrapper<SSettleLettersDetail> condition = new LambdaQueryWrapper<>();
        condition.ge(SSettleLettersDetail::getSettleStart, queryVo.getSettleStart());
        condition.le(SSettleLettersDetail::getSettleEnd, queryVo.getSettleEnd());
        condition.eq(SSettleLettersDetail::getDataStatus, 0);
        if (StringUtils.isNotEmpty(queryVo.getOrderSource())) {
            condition.eq(SSettleLettersDetail::getOrderSource, queryVo.getOrderSource());
        }
        if (StringUtils.isNotEmpty(queryVo.getMerchantCode())) {
            condition.eq(SSettleLettersDetail::getMerchantCode, queryVo.getMerchantCode());
        }
        if (StringUtils.isNotEmpty(queryVo.getOrgCode())) {
            condition.eq(SSettleLettersDetail::getOrgCode, queryVo.getOrgCode());
        }
        if(queryVo.getLettersType()!=null){
            condition.eq(SSettleLettersDetail::getLettersType, queryVo.getLettersType());
        }
        if(StringUtils.isNotEmpty(queryVo.getRevenueType())){
            condition.eq(SSettleLettersDetail::getRevenueType, queryVo.getRevenueType());
        }
        PageInfo<SSettleLettersDetail> pageInfo = this.getBaseMapper().find(condition, queryVo.getCurrentPage(), queryVo.getPageSize());
        List<SSettleLettersDetailResVO> collect=null;
        if(!CollectionUtils.isEmpty(pageInfo.getList())){
            collect= pageInfo.getList().stream().map(l -> {
                SSettleLettersDetailResVO vo = ObjectConvertUtil.convert(l, SSettleLettersDetailResVO.class).get();
                vo.setOrderSourceCn(OrderSourceEnum.getDesc(vo.getOrderSource()));
                vo.setRevenueTypeCn(RevenueTypeEnum.getDesc(vo.getRevenueType()));
                return vo;
            }).collect(Collectors.toList());

        }
        return new PageInfo<SSettleLettersDetailResVO>(collect,pageInfo.getPagination());
    }

    @Override
    public void deleteBySettleLettersCode(String settleLettersCode) {
        LambdaQueryWrapper<SSettleLettersDetail> condition = new LambdaQueryWrapper<>();
        SSettleLettersDetail entity = new SSettleLettersDetail();
        entity.setDataStatus(1);
        // 标记明细记录失效
        this.getBaseMapper().update(entity, condition.eq(SSettleLettersDetail::getSettleLettersCode, settleLettersCode));
    }

    @Override
    public void deleteBySettleLettersCode(List<String> cods) {
        LambdaQueryWrapper<SSettleLettersDetail> condition = new LambdaQueryWrapper<>();
        SSettleLettersDetail entity = new SSettleLettersDetail();
        entity.setDataStatus(1);
        // 标记明细记录失效
        this.getBaseMapper().update(entity, condition.in(SSettleLettersDetail::getSettleLettersCode, cods));
    }

    @Override
    public List<SSettleLettersDetail> queryByParentSettleLetter(String parentCode) {
        LambdaQueryWrapper<SSettleLettersDetail> condition = new LambdaQueryWrapper<>();
        condition.eq(SSettleLettersDetail::getLettersType, LettersTypeEnum.NORMAL.getCode());
        condition.eq(SSettleLettersDetail::getSettleLettersCode, parentCode);
        condition.eq(SSettleLettersDetail::getDataStatus, 0);
        return this.getBaseMapper().selectList(condition);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void adjust(SettleLetterAdjustVo settleLetterAdjustVo) {
        LambdaQueryWrapper<SSettleLettersDetail> condition = new LambdaQueryWrapper<>();
        //condition.eq(SSettleLettersDetail::getLettersType, LettersTypeEnum.NORMAL.getCode());
        condition.eq(SSettleLettersDetail::getSettleLettersCode, settleLetterAdjustVo.getSettleLettersCode());
        condition.eq(SSettleLettersDetail::getSubSettleLettersCode, settleLetterAdjustVo.getSubSettleLettersCode()).or()
                .eq(SSettleLettersDetail::getOriginalLettersCode, settleLetterAdjustVo.getSubSettleLettersCode());
        condition.eq(SSettleLettersDetail::getDataStatus, 0);
        List<SSettleLettersDetail> sSettleLettersDetails = this.getBaseMapper().selectList(condition);
        REVENUE_SETTLE_LETTERS_NOT_FOUND_ERROR.assertIsTrue(!CollectionUtils.isEmpty(sSettleLettersDetails));
        List<SSettleLettersDetail> adjustList = sSettleLettersDetails.stream().filter(s -> s.getLettersType().equals(LettersTypeEnum.MANUAL_ADJUST.getCode())).collect(Collectors.toList());
        List<SSettleLettersDetail> normalList = sSettleLettersDetails.stream().filter(s -> s.getLettersType().equals(LettersTypeEnum.NORMAL.getCode())).collect(Collectors.toList());

        if (null == settleLetterAdjustVo.getId() && CollectionUtils.isEmpty(adjustList)) {
            // 新增的手动对账函
            SSettleLettersDetail newSettleLettersDetail = ObjectConvertUtil.convert(normalList.get(0), SSettleLettersDetail.class).get();
            newSettleLettersDetail.setId(null);
            newSettleLettersDetail.setCreatedBy(null);
            newSettleLettersDetail.setCreatedDt(LocalDateTime.now());
            newSettleLettersDetail.setLastUpdDt(null);
            newSettleLettersDetail.setLastUpdBy(null);
            newSettleLettersDetail.setSettleLettersFile(null);
            newSettleLettersDetail.setOriginalLettersCode(normalList.get(0).getSubSettleLettersCode());
            newSettleLettersDetail.setTotalOrderAmount(settleLetterAdjustVo.getTotalOrderAmount());
            newSettleLettersDetail.setTotalDiscount(settleLetterAdjustVo.getTotalDiscount());
            newSettleLettersDetail.setTotalRevenueAmount(settleLetterAdjustVo.getTotalRevenueAmount());
            newSettleLettersDetail.setScOrderCount(settleLetterAdjustVo.getScOrderCount());
            newSettleLettersDetail.setSubSettleLettersCode(idGenerateUtil.getSettleLetterCode());
            newSettleLettersDetail.setSettleLettersFile(settleLetterAdjustVo.getAdjustDetailFile());
            newSettleLettersDetail.setAdjustNote(settleLetterAdjustVo.getAdjustNote());
            newSettleLettersDetail.setLettersType(LettersTypeEnum.MANUAL_ADJUST.getCode());
            this.getBaseMapper().insert(newSettleLettersDetail);
        } else {
            //修改手动调整单
            SSettleLettersDetail updateEntity = new SSettleLettersDetail();
            updateEntity.setOriginalLettersCode(normalList.get(0).getSubSettleLettersCode());
            updateEntity.setTotalOrderAmount(settleLetterAdjustVo.getTotalOrderAmount());
            updateEntity.setTotalDiscount(settleLetterAdjustVo.getTotalDiscount());
            updateEntity.setTotalRevenueAmount(settleLetterAdjustVo.getTotalRevenueAmount());
            updateEntity.setScOrderCount(settleLetterAdjustVo.getScOrderCount());
            updateEntity.setSettleLettersFile(settleLetterAdjustVo.getAdjustDetailFile());
            updateEntity.setAdjustCount(adjustList.get(0).getAdjustCount() + 1);
            updateEntity.setAdjustNote(settleLetterAdjustVo.getAdjustNote());
            LambdaQueryWrapper<SSettleLettersDetail> updateCondition = new LambdaQueryWrapper<>();
            updateCondition.eq(SSettleLettersDetail::getId, adjustList.get(0).getId());
            updateCondition.eq(SSettleLettersDetail::getSettleLettersCode, adjustList.get(0).getSettleLettersCode());
            updateCondition.eq(SSettleLettersDetail::getSubSettleLettersCode, adjustList.get(0).getSubSettleLettersCode());
            this.getBaseMapper().update(updateEntity, updateCondition);
            this.getBaseMapper().updateAdjustCount(settleLetterAdjustVo.getSettleLettersCode(),settleLetterAdjustVo.getSubSettleLettersCode(),1);
        }
        // 修改主表的调整次数
        settleLettersService.updateAdjustCount(settleLetterAdjustVo.getSettleLettersCode(),1);

    }

    @Override
    public SSettleLettersDetail queryAdjustBySubSettleLettersCode(String subSettleLettersCode) {
        LambdaQueryWrapper<SSettleLettersDetail> condition = new LambdaQueryWrapper<>();
        condition.eq(SSettleLettersDetail::getLettersType, LettersTypeEnum.NORMAL.getCode());
        condition.eq(SSettleLettersDetail::getSubSettleLettersCode, subSettleLettersCode);
        condition.eq(SSettleLettersDetail::getDataStatus, 0);
        condition.eq(SSettleLettersDetail::getLettersType,LettersTypeEnum.MANUAL_ADJUST.getCode());
        return this.getBaseMapper().selectOne(condition);
    }

    @Override
    public void export(SSettleLettersDetailQueryVo params, HttpServletRequest request, HttpServletResponse response)  throws Exception {
        params.setPageSize(10000);
        params.setCurrentPage(1);
        try {
            PageInfo<SSettleLettersDetailResVO> page = this.queryLit(SSettleLettersDetailQueryBO.build(params));
            if(page!=null && !CollectionUtils.isEmpty(page.getList())){
                String fileName = String.format("%s到%s手动调整单.xlsx", DateTimeUtil.format(params.getSettleStart(), DateTimeUtil.yyyyMMdd),DateTimeUtil.format(params.getSettleEnd(), DateTimeUtil.yyyyMMdd));
                String[] allTitleSummary = {"收入函编码", "收入函子编码", "收入确认类型", "场景", "商户名称", "调整销售金额", "调整优惠金额", "调整结算金额", "调整服务成功笔数", "调整收入", "调整时间", "调整原因"};
                List<SSettleLettersDetailExportBo> list=new ArrayList<SSettleLettersDetailExportBo>();
                for (SSettleLettersDetailResVO d : page.getList()) {
                    list.add(new SSettleLettersDetailExportBo(
                            d.getSettleLettersCode(),d.getOriginalLettersCode(),d.getRevenueTypeCn(),d.getOrderSourceCn(),
                            d.getMerchantName(),AmountUtil.getYUAN(d.getTotalOrderAmount()),AmountUtil.getYUAN(d.getTotalDiscount()),
                            AmountUtil.getYUAN(d.getTotalProductCost()),d.getScOrderCount(),AmountUtil.getYUAN(d.getTotalRevenueAmount()),
                            d.getCreatedDt(),d.getAdjustNote()
                    ));
                }
                ExportBO exportBOSummary = new ExportBO(fileName.replace(".xlsx",""), null, allTitleSummary, list);
                Workbook workbook = ExcelUtil.buildExcelWorkBook(Collections.singletonList(exportBOSummary));
                ExcelUtil.exportExcle(request, response, workbook, fileName);
            }
        }catch (Exception e) {
            log.error("批量导出对账汇总异常:{}",e.getMessage());
            throw new Exception("导出失败" ,e);
        }
    }

    @Override
    public void uploadAdjust(SSettleLettersDetail detail) {
        if(StringUtils.isNotEmpty(detail.getOriginalLettersCode()) && StringUtils.isNotEmpty(detail.getAdjustDetailFile())){
            LambdaQueryWrapper<SSettleLettersDetail> condition = new LambdaQueryWrapper<>();
            condition.eq(SSettleLettersDetail::getSubSettleLettersCode,detail.getOriginalLettersCode())
            .or().eq(SSettleLettersDetail::getOriginalLettersCode,detail.getOriginalLettersCode());
            condition.eq(SSettleLettersDetail::getDataStatus,0);
            SSettleLettersDetail entity = new SSettleLettersDetail();
            entity.setAdjustDetailFile(detail.getAdjustDetailFile());
            this.getBaseMapper().update(entity,condition);
        }
    }
}
